﻿using System.Web.Security;
using System.Configuration.Provider;
using System.Collections.Specialized;
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.Odbc;
using System.Configuration;
using System.Diagnostics;
using System.Web;
using System.Globalization;
using System.Security.Cryptography;
using System.Text;
using System.Web.Configuration;
using Google.GData.Client;
using Google.GData.Extensions;
using Google.GData.Spreadsheets;

namespace Sriram.GoogleProviders
{
    public class GoogleSpreadsheetMembershipProvider : MembershipProvider
    {
        //
        // generated password length.
        //

        private int newPasswordLength = 8;

        //
        // System.Configuration.Provider.ProviderBase.Initialize Method
        //

        public override void Initialize(string name, NameValueCollection config)
        {
            //
            // Initialize values from web.config.
            //


            if (config == null)
                throw new ArgumentNullException("config");

            if (name == null || name.Length == 0)
                name = "GoogleSpreadsheetMembershipProvider";

            if (String.IsNullOrEmpty(config["description"]))
            {
                config.Remove("description");
                config.Add("description", "Google Spreadsheet Membership Provider");
            }

            // Initialize the abstract base class.
            base.Initialize(name, config);

            pApplicationName = ProviderUtil.GetConfigValue(config["applicationName"],
                                            System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath);
            pMaxInvalidPasswordAttempts = Convert.ToInt32(ProviderUtil.GetConfigValue(config["maxInvalidPasswordAttempts"], "5"));
            pPasswordAttemptWindow = Convert.ToInt32(ProviderUtil.GetConfigValue(config["passwordAttemptWindow"], "10"));
            pMinRequiredNonAlphanumericCharacters = Convert.ToInt32(ProviderUtil.GetConfigValue(config["minRequiredNonAlphanumericCharacters"], "1"));
            pMinRequiredPasswordLength = Convert.ToInt32(ProviderUtil.GetConfigValue(config["minRequiredPasswordLength"], "7"));
            pPasswordStrengthRegularExpression = Convert.ToString(ProviderUtil.GetConfigValue(config["passwordStrengthRegularExpression"], ""));
            pEnablePasswordReset = Convert.ToBoolean(ProviderUtil.GetConfigValue(config["enablePasswordReset"], "true"));
            pEnablePasswordRetrieval = Convert.ToBoolean(ProviderUtil.GetConfigValue(config["enablePasswordRetrieval"], "true"));
            pRequiresQuestionAndAnswer = Convert.ToBoolean(ProviderUtil.GetConfigValue(config["requiresQuestionAndAnswer"], "false"));
            pRequiresUniqueEmail = Convert.ToBoolean(ProviderUtil.GetConfigValue(config["requiresUniqueEmail"], "true"));
            pGoogleID = Convert.ToString(ProviderUtil.GetConfigValue(config["googleID"], ""));
            pGooglePassword = Convert.ToString(ProviderUtil.GetConfigValue(config["googlePassword"], ""));


            string temp_format = config["passwordFormat"];
            if (temp_format == null)
            {
                temp_format = "Clear";
            }

            switch (temp_format)
            {
                case "Hashed":
                    pPasswordFormat = MembershipPasswordFormat.Hashed;
                    break;
                case "Encrypted":
                    pPasswordFormat = MembershipPasswordFormat.Encrypted;
                    break;
                case "Clear":
                    pPasswordFormat = MembershipPasswordFormat.Clear;
                    break;
                default:
                    throw new ProviderException("Password format not supported.");
            }

        }





        //
        // System.Web.Security.MembershipProvider properties.
        //


        private string pApplicationName;
        private bool pEnablePasswordReset;
        private bool pEnablePasswordRetrieval;
        private bool pRequiresQuestionAndAnswer;
        private bool pRequiresUniqueEmail;
        private int pMaxInvalidPasswordAttempts;
        private int pPasswordAttemptWindow;
        private MembershipPasswordFormat pPasswordFormat;
        private string pGoogleID;
        private string pGooglePassword;
        public override string ApplicationName
        {
            get { return pApplicationName; }
            set { pApplicationName = value; }
        }

        public override bool EnablePasswordReset
        {
            get { return pEnablePasswordReset; }
        }


        public override bool EnablePasswordRetrieval
        {
            get { return pEnablePasswordRetrieval; }
        }


        public override bool RequiresQuestionAndAnswer
        {
            get { return pRequiresQuestionAndAnswer; }
        }


        public override bool RequiresUniqueEmail
        {
            get { return pRequiresUniqueEmail; }
        }


        public override int MaxInvalidPasswordAttempts
        {
            get { return pMaxInvalidPasswordAttempts; }
        }


        public override int PasswordAttemptWindow
        {
            get { return pPasswordAttemptWindow; }
        }


        public override MembershipPasswordFormat PasswordFormat
        {
            get { return pPasswordFormat; }
        }

        private int pMinRequiredNonAlphanumericCharacters;

        public override int MinRequiredNonAlphanumericCharacters
        {
            get { return pMinRequiredNonAlphanumericCharacters; }
        }

        private int pMinRequiredPasswordLength;

        public override int MinRequiredPasswordLength
        {
            get { return pMinRequiredPasswordLength; }
        }

        private string pPasswordStrengthRegularExpression;

        public override string PasswordStrengthRegularExpression
        {
            get { return pPasswordStrengthRegularExpression; }
        }

        public string GoogleID
        {
            get { return pGoogleID; }
            set { pGoogleID = value; }
        }
        public string GooglePassword
        {
            get { return pGooglePassword; }
            set { pGooglePassword = value; }
        }

        //
        // System.Web.Security.MembershipProvider methods.
        //

        public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
        {
            ValidatePasswordEventArgs args =
              new ValidatePasswordEventArgs(username, password, true);

            OnValidatingPassword(args);

            if (args.Cancel)
            {
                status = MembershipCreateStatus.InvalidPassword;
                return null;
            }



            if (RequiresUniqueEmail && GetUserNameByEmail(email) != "")
            {
                status = MembershipCreateStatus.DuplicateEmail;
                return null;
            }

            MembershipUser u = GetUser(username, false);

            if (u == null)
            {
                DateTime createDate = DateTime.Now;

                if (providerUserKey == null)
                {
                    providerUserKey = Guid.NewGuid();
                }
                else
                {
                    if (!(providerUserKey is Guid))
                    {
                        status = MembershipCreateStatus.InvalidProviderUserKey;
                        return null;
                    }
                }
                GoogleContext context = new GoogleContext(GoogleID, GooglePassword);
                ListFeed lfeed = context.GetGoogleSpreadsheetMembershipListFeed();
                //ListEntry firstRow = lfeed.Entries[0] as ListEntry;

                ListEntry newRow = new ListEntry();
                ListEntry.Custom PKID = new ListEntry.Custom();
                //google requries lower case column name
                PKID.LocalName = "PKID".ToLower();
                PKID.Value = providerUserKey.ToString();
                newRow.Elements.Add(PKID);
                ListEntry.Custom Username = new ListEntry.Custom();
                Username.LocalName = "Username".ToLower();
                Username.Value = username;
                newRow.Elements.Add(Username);
                ListEntry.Custom Password = new ListEntry.Custom();
                Password.LocalName = "Password".ToLower();
                Password.Value = password;
                newRow.Elements.Add(Password);
                ListEntry.Custom Email = new ListEntry.Custom();
                Email.LocalName = "Email".ToLower();
                Email.Value = email;
                newRow.Elements.Add(Email);
                ListEntry.Custom PasswordQuestion = new ListEntry.Custom();
                PasswordQuestion.LocalName = "PasswordQuestion".ToLower();
                PasswordQuestion.Value = passwordQuestion;
                newRow.Elements.Add(PasswordQuestion);
                ListEntry.Custom PasswordAnswer = new ListEntry.Custom();
                PasswordAnswer.LocalName = "PasswordAnswer".ToLower();
                PasswordAnswer.Value = passwordAnswer;
                newRow.Elements.Add(PasswordAnswer);
                ListEntry.Custom IsApproved = new ListEntry.Custom();
                IsApproved.LocalName = "IsApproved".ToLower();
                IsApproved.Value = isApproved.ToString().ToLower();
                newRow.Elements.Add(IsApproved);
                //Comment column not implemented as it is always empty
                ListEntry.Custom CreationDate = new ListEntry.Custom();
                CreationDate.LocalName = "CreationDate".ToLower();
                CreationDate.Value = createDate.ToString();
                newRow.Elements.Add(CreationDate);
                ListEntry.Custom LastPasswordChangedDate = new ListEntry.Custom();
                LastPasswordChangedDate.LocalName = "LastPasswordChangedDate".ToLower();
                LastPasswordChangedDate.Value = createDate.ToString();
                newRow.Elements.Add(LastPasswordChangedDate);
                ListEntry.Custom LastActivityDate = new ListEntry.Custom();
                LastActivityDate.LocalName = "LastActivityDate".ToLower();
                LastActivityDate.Value = createDate.ToString();
                newRow.Elements.Add(LastActivityDate);
                ListEntry.Custom ApplicationName = new ListEntry.Custom();
                ApplicationName.LocalName = "ApplicationName".ToLower();
                ApplicationName.Value = pApplicationName;
                newRow.Elements.Add(ApplicationName);
                ListEntry.Custom IsLockedOut = new ListEntry.Custom();
                IsLockedOut.LocalName = "IsLockedOut".ToLower();
                IsLockedOut.Value = "false";
                newRow.Elements.Add(IsLockedOut);
                ListEntry.Custom LastLockedOutDate = new ListEntry.Custom();
                LastLockedOutDate.LocalName = "LastLockedOutDate".ToLower();
                LastLockedOutDate.Value = createDate.ToString();
                newRow.Elements.Add(LastLockedOutDate);
                ListEntry.Custom FailedPasswordAttemptCount = new ListEntry.Custom();
                FailedPasswordAttemptCount.LocalName = "FailedPasswordAttemptCount".ToLower();
                FailedPasswordAttemptCount.Value = "0";
                newRow.Elements.Add(FailedPasswordAttemptCount);
                ListEntry.Custom FailedPasswordAttemptWindowStart = new ListEntry.Custom();
                FailedPasswordAttemptWindowStart.LocalName = "FailedPasswordAttemptWindowStart".ToLower();
                FailedPasswordAttemptWindowStart.Value = createDate.ToString();
                newRow.Elements.Add(FailedPasswordAttemptWindowStart);
                ListEntry.Custom FailedPasswordAnswerAttemptCount = new ListEntry.Custom();
                FailedPasswordAnswerAttemptCount.LocalName = "FailedPasswordAnswerAttemptCount".ToLower();
                FailedPasswordAnswerAttemptCount.Value = "0";
                newRow.Elements.Add(FailedPasswordAnswerAttemptCount);
                ListEntry.Custom FailedPasswordAnswerAttemptWindowStart = new ListEntry.Custom();
                FailedPasswordAnswerAttemptWindowStart.LocalName = "FailedPasswordAnswerAttemptWindowStart".ToLower();
                FailedPasswordAnswerAttemptWindowStart.Value = createDate.ToString();
                newRow.Elements.Add(FailedPasswordAnswerAttemptWindowStart);
                try
                {
                    ListEntry insertedRow = lfeed.Insert(newRow);

                    int recAdded = insertedRow.Elements.Count;

                    if (recAdded > 0)
                    {
                        status = MembershipCreateStatus.Success;
                    }
                    else
                    {
                        status = MembershipCreateStatus.UserRejected;
                    }
                }
                catch
                {

                    status = MembershipCreateStatus.ProviderError;
                }
                return GetUser(username, false);
            }
            else
            {
                status = MembershipCreateStatus.DuplicateUserName;
            }


            return u;
        }

        public override MembershipUser GetUser(string username, bool userIsOnline)
        {
            GoogleContext context = new GoogleContext(GoogleID, GooglePassword);
            MembershipUser u = null;
            try
            {
                ListFeed lfeed = context.GetGoogleSpreadsheetMembershipListFeed("username=" + username);
                ListEntry firstRow = lfeed.Entries[0] as ListEntry;

                if (firstRow.Elements.Count > 0)
                {

                    u = ProviderUtil.GetUserFromSpreadsheet(this.Name, firstRow);

                    if (userIsOnline)
                    {
                        ListEntry.Custom LastActivityDate = firstRow.Elements[10];
                        LastActivityDate.Value = DateTime.Now.ToString();
                        ListEntry updatedRow = firstRow.Update() as ListEntry;
                    }
                }

            }
            catch
            {
                return u;
            }
            return u;
        }

        public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
        {
            GoogleContext context = new GoogleContext(GoogleID, GooglePassword);
            MembershipUser u = null;
            try
            {
                ListFeed lfeed = context.GetGoogleSpreadsheetMembershipListFeed("pkid=" + providerUserKey.ToString());
                ListEntry firstRow = lfeed.Entries[0] as ListEntry;

                if (firstRow.Elements.Count > 0)
                {

                    u = ProviderUtil.GetUserFromSpreadsheet(this.Name, firstRow);

                    if (userIsOnline)
                    {
                        ListEntry.Custom LastActivityDate = firstRow.Elements[10];
                        LastActivityDate.Value = DateTime.Now.ToString();
                        ListEntry updatedRow = firstRow.Update() as ListEntry;
                    }
                }

            }
            catch
            {
                return u;
            }
            return u;
        }

        public override bool ChangePassword(string username, string oldPassword, string newPassword)
        {
            if (!ValidateUser(username, oldPassword))
                return false;


            ValidatePasswordEventArgs args =
              new ValidatePasswordEventArgs(username, newPassword, true);

            OnValidatingPassword(args);

            if (args.Cancel)
                if (args.FailureInformation != null)
                {
                    //throw args.FailureInformation;
                }
                else
                {
                    throw new MembershipPasswordException("Change password canceled due to new password validation failure.");
                }


            GoogleContext context = new GoogleContext(GoogleID, GooglePassword);


            //int rowsAffected = 0;

            try
            {
                ListFeed lfeed = context.GetGoogleSpreadsheetMembershipListFeed("username=" + username);
                ListEntry firstRow = lfeed.Entries[0] as ListEntry;
                ListEntry.Custom LastPasswordChangedDate = firstRow.Elements[9];
                LastPasswordChangedDate.Value = DateTime.Now.ToString();
                ListEntry.Custom Password = firstRow.Elements[2];
                Password.Value = newPassword;
                ListEntry updatedRow = firstRow.Update() as ListEntry;
                return true;
            }
            catch (Exception e)
            {
                throw e;
            }

            //return false;
        }

        public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
        {
            if (!ValidateUser(username, password))
                return false;

            GoogleContext context = new GoogleContext(GoogleID, GooglePassword);


            //int rowsAffected = 0;

            try
            {
                ListFeed lfeed = context.GetGoogleSpreadsheetMembershipListFeed("username=" + username);
                ListEntry firstRow = lfeed.Entries[0] as ListEntry;
                ListEntry.Custom PasswordQuestion = firstRow.Elements[4];
                PasswordQuestion.Value = newPasswordQuestion;
                ListEntry.Custom PasswordAnswer = firstRow.Elements[5];
                PasswordAnswer.Value = newPasswordAnswer;
                ListEntry updatedRow = firstRow.Update() as ListEntry;
                return true;

            }
            catch (Exception e)
            {
                throw e;
            }



        }

        public override bool DeleteUser(string username, bool deleteAllRelatedData)
        {
            GoogleContext context = new GoogleContext(GoogleID, GooglePassword);           
            try
            {
                ListFeed lfeed = context.GetGoogleSpreadsheetMembershipListFeed("username=" + username);
                ListEntry firstRow = lfeed.Entries[0] as ListEntry;
                firstRow.Delete();
                if (deleteAllRelatedData)
                {
                    //implement later
                // Process commands to delete all data for the user in the database.
                }
                return false;
            }
            catch (Exception e)
            {
                throw e;
            }           

            
        }

        public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
        {
            GoogleContext context = new GoogleContext(GoogleID, GooglePassword);   
            MembershipUserCollection users = new MembershipUserCollection();
            totalRecords = 0;
            try
            {
                ListFeed lfeed = context.GetGoogleSpreadsheetMembershipListFeed("email=" + emailToMatch);
                totalRecords = lfeed.Entries.Count;
                if (totalRecords <= 0) { return users; }     
                int counter = 0;
                int startIndex = pageSize * pageIndex;
                int endIndex = startIndex + pageSize - 1;

                foreach (ListEntry i in lfeed.Entries)
                { 
                    if (counter >= startIndex)
                    {
                        MembershipUser u = ProviderUtil.GetUserFromSpreadsheet(this.Name, i);
                        users.Add(u);
                    }

                    if (counter >= endIndex) { break; }
                    counter++;
                }
            }
            catch (Exception e)
            {
                throw e;            
            }
            return users;
        }

        public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
        {
            GoogleContext context = new GoogleContext(GoogleID, GooglePassword);
            MembershipUserCollection users = new MembershipUserCollection();
            try
            {
                ListFeed lfeed = context.GetGoogleSpreadsheetMembershipListFeed("username=" + usernameToMatch);
                totalRecords = lfeed.Entries.Count;
                if (totalRecords <= 0) { return users; }
                int counter = 0;
                int startIndex = pageSize * pageIndex;
                int endIndex = startIndex + pageSize - 1;

                foreach (ListEntry i in lfeed.Entries)
                {
                    if (counter >= startIndex)
                    {
                        MembershipUser u = ProviderUtil.GetUserFromSpreadsheet(this.Name,i);
                        users.Add(u);
                    }
                    if (counter >= endIndex) { break; }
                    counter++;
                }
            }
            catch (Exception e)
            {
                throw e;
            }         

            return users;
        }

        public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
        {
            GoogleContext context = new GoogleContext(GoogleID, GooglePassword); 
            MembershipUserCollection users = new MembershipUserCollection();
            totalRecords = 0;
            try
            {
                ListFeed lfeed = context.GetGoogleSpreadsheetMembershipListFeed();                
                totalRecords = lfeed.Entries.Count;
                if (totalRecords <= 0) { return users; }
                int counter = 0;
                int startIndex = pageSize * pageIndex;
                int endIndex = startIndex + pageSize - 1;
                foreach (ListEntry i in lfeed.Entries)
                {
                    if (counter >= startIndex)
                    {
                        MembershipUser u = ProviderUtil.GetUserFromSpreadsheet(this.Name, i);
                        users.Add(u);
                    }
                    if (counter >= endIndex) 
                    {
                        break;
                    }
                    counter++;
                }               
            }
            catch (Exception e)
            {
                throw e;
            }
            return users;
        }

        public override int GetNumberOfUsersOnline()
        {
            TimeSpan onlineSpan = new TimeSpan(0, System.Web.Security.Membership.UserIsOnlineTimeWindow, 0);
            DateTime compareTime = DateTime.Now.Subtract(onlineSpan);
            GoogleContext context = new GoogleContext(GoogleID, GooglePassword);     
            int numOnline = 0;
            try
            {
                ListFeed lfeed = context.GetGoogleSpreadsheetMembershipListFeed("lastactivitydate>" + compareTime);
                numOnline = lfeed.Entries.Count;
            }
            catch (OdbcException e)
            {
                throw e;
            }  
            return numOnline;
        }

        public override string GetPassword(string username, string answer)
        {
            if (!EnablePasswordRetrieval)
            {
                throw new ProviderException("Password Retrieval Not Enabled.");
            }

            if (PasswordFormat == MembershipPasswordFormat.Hashed)
            {
                throw new ProviderException("Cannot retrieve Hashed passwords.");
            }

            GoogleContext context = new GoogleContext(GoogleID, GooglePassword);
            MembershipUserCollection users = new MembershipUserCollection();
           

            string password = "";
            string passwordAnswer = "";
            //OdbcDataReader reader = null;

            try
            {
                ListFeed lfeed = context.GetGoogleSpreadsheetMembershipListFeed("username=" + username);
                ListEntry firstRow = lfeed.Entries[0] as ListEntry;

                if (firstRow.Elements.Count > 0)
                {
                    bool IsLockedOut = Convert.ToBoolean(firstRow.Elements[12].Value);
                    if (IsLockedOut)
                    {
                        throw new MembershipPasswordException("The supplied user is locked out.");
                    }

                    password = firstRow.Elements[2].Value;
                    passwordAnswer = firstRow.Elements[5].Value;
                }
                else
                {
                    throw new MembershipPasswordException("The supplied user name is not found.");
                }
            }
            catch (Exception e)
            {
                throw e;
            }         


            if (RequiresQuestionAndAnswer && !ProviderUtil.CheckPassword(answer, passwordAnswer))
            {
                //implement later
                //UpdateFailureCount(username, "passwordAnswer");

                throw new MembershipPasswordException("Incorrect password answer.");
            }

            //Implement later
            //if (PasswordFormat == MembershipPasswordFormat.Encrypted)
            //{
            //    password = UnEncodePassword(password);
            //}

            return password;
        }

        public override string GetUserNameByEmail(string email)
        {
            GoogleContext context = new GoogleContext(GoogleID, GooglePassword);
            string username = "";
            try
            {
                //ListFeed lfeed = context.GetGoogleSpreadsheetMembershipListFeed("{email}%3d%22"+HttpContext.Current.Server.UrlEncode(email)+"%22");
                ListFeed lfeed = context.GetGoogleSpreadsheetMembershipListFeed("email=" + email);
                if (lfeed.Entries.Count > 0)
                {
                    ListEntry firstRow = lfeed.Entries[0] as ListEntry;
                    username = firstRow.Elements[1].Value;
                }
            }
            catch (Exception e)
            {
                throw e;
            }            
            return username;
        }

        public override string ResetPassword(string username, string answer)
        {
            if (!EnablePasswordReset)
            {
                throw new NotSupportedException("Password reset is not enabled.");
            }

            if (answer == null && RequiresQuestionAndAnswer)
            {
                //implement later
                //UpdateFailureCount(username, "passwordAnswer");

                throw new ProviderException("Password answer required for password reset.");
            }

            string newPassword = System.Web.Security.Membership.GeneratePassword(newPasswordLength, MinRequiredNonAlphanumericCharacters);


            ValidatePasswordEventArgs args = new ValidatePasswordEventArgs(username, newPassword, true);

            OnValidatingPassword(args);

            if (args.Cancel)
            {
                if (args.FailureInformation != null)
                {
                    throw args.FailureInformation;
                }
                else
                {
                    throw new MembershipPasswordException("Reset password canceled due to password validation failure.");
                }
            }

            GoogleContext context = new GoogleContext(GoogleID, GooglePassword);  
            string passwordAnswer = "";    
            try
            {
                ListFeed lfeed = context.GetGoogleSpreadsheetMembershipListFeed("username=" + username);
                ListEntry firstRow = lfeed.Entries[0] as ListEntry;
                if (lfeed.Entries.Count > 0)
                {                    
                    bool IsLockedOut = Convert.ToBoolean(firstRow.Elements[12].Value);
                    if (IsLockedOut)
                    {
                        throw new MembershipPasswordException("The supplied user is locked out.");
                    }

                    passwordAnswer = firstRow.Elements[5].Value;
                }
                else
                {
                    throw new MembershipPasswordException("The supplied user name is not found.");
                }
                if (RequiresQuestionAndAnswer && ! ProviderUtil.CheckPassword(answer, passwordAnswer))
                {
                    //implement later
                    //UpdateFailureCount(username, "passwordAnswer");

                    throw new MembershipPasswordException("Incorrect password answer.");
                }
                ListEntry.Custom LastPasswordChangedDate = firstRow.Elements[9];
                LastPasswordChangedDate.Value = DateTime.Now.ToString();
                ListEntry.Custom Password = firstRow.Elements[9];
                //implement later
                //Password.Value = EncodePassword(newPassword);
                Password.Value = newPassword;
                ListEntry updatedRow = firstRow.Update() as ListEntry; 
                return newPassword;
            }
            catch (Exception e)
            {
                throw e;            
            }
            //implement later
            //if (rowsAffected > 0)
            //{
            //    return newPassword;
            //}
            //else
            //{
            //    throw new MembershipPasswordException("User not found, or user is locked out. Password not Reset.");
            //}
        }

        public override bool UnlockUser(string username)
        {
            GoogleContext context = new GoogleContext(GoogleID, GooglePassword);
            int rowsAffected = 0;
            try
            {
                ListFeed lfeed = context.GetGoogleSpreadsheetMembershipListFeed("username=" + username);
                ListEntry firstRow = lfeed.Entries[0] as ListEntry;
                ListEntry.Custom LastLockedOutDate = firstRow.Elements[13];
                LastLockedOutDate.Value = DateTime.Now.ToString();
                ListEntry.Custom IsLockedOut = firstRow.Elements[9];
                IsLockedOut.Value = false.ToString();
                ListEntry updatedRow = firstRow.Update() as ListEntry;
                rowsAffected = 1;
            }
            catch (Exception e)
            {
                throw e;
            }

            if (rowsAffected > 0)
            {
                return true;
            }
            return false;      
        }

        public override void UpdateUser(MembershipUser user)
        {
            GoogleContext context = new GoogleContext(GoogleID, GooglePassword);            
            try
            {
                ListFeed lfeed = context.GetGoogleSpreadsheetMembershipListFeed("username=" + user.UserName);
                ListEntry firstRow = lfeed.Entries[0] as ListEntry;
                ListEntry.Custom Email = firstRow.Elements[3];
                Email.Value = user.Email;
                ListEntry.Custom Comment = firstRow.Elements[7];
                Comment.Value = user.Comment;
                ListEntry.Custom IsApproved = firstRow.Elements[6];
                IsApproved.Value = user.IsApproved.ToString();
                ListEntry updatedRow = firstRow.Update() as ListEntry;
                
            }
            catch (Exception e)
            {
                throw e;
            }           
        }

        public override bool ValidateUser(string username, string password)
        {
            bool isValid = false;
            GoogleContext context = new GoogleContext(GoogleID, GooglePassword);
            bool isApproved = false;
            string pwd = "";
            try
            {
                ListFeed lfeed = context.GetGoogleSpreadsheetMembershipListFeed("username=" + username + "&islockedout=FALSE");
                ListEntry firstRow = lfeed.Entries[0] as ListEntry;

                if (firstRow.Elements.Count > 0)
                {
                    pwd = firstRow.Elements[2].Value;
                    isApproved = firstRow.Elements[6].Value == "TRUE" ? true : false;
                }
                else
                {
                    return false;
                }

                if (ProviderUtil.CheckPassword(password, pwd))
                {
                    if (isApproved)
                    {
                        isValid = true;
                        ListEntry.Custom LastLoginDate = firstRow.Elements[18];
                        LastLoginDate.Value = DateTime.Now.ToString();
                        ListEntry updatedRow = firstRow.Update() as ListEntry;
                    }
                }
                //implement later 
                //else
                //{
                //    conn.Close();

                //    UpdateFailureCount(username, "password");
                //}
            }
            catch (Exception e)
            {
                throw e;
            }

            return isValid;
        }
    }
        
       
}
